package org.tuoren.system.service.impl;

import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.tuoren.common.core.utils.MapstructUtils;
import org.tuoren.common.core.utils.StringUtils;
import org.tuoren.common.core.utils.ip.AddressUtils;
import org.tuoren.common.log.event.VisitLogEvent;
import org.tuoren.common.mybatis.core.page.PageQuery;
import org.tuoren.common.mybatis.core.page.TableDataInfo;
import org.tuoren.system.domain.SysVisitLog;
import org.tuoren.system.domain.bo.SysVisitLogBo;
import org.tuoren.system.domain.vo.SysDictDataVo;
import org.tuoren.system.domain.vo.SysVisitLogVo;
import org.tuoren.system.mapper.SysDictDataMapper;
import org.tuoren.system.mapper.SysVisitLogMapper;
import org.tuoren.system.service.ISysVisitLogService;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 浏览日志 服务层处理
 *
 * @author Lion Li
 */
@RequiredArgsConstructor
@Service
public class SysVisitLogServiceImpl implements ISysVisitLogService {

    private final SysVisitLogMapper baseMapper;

    private final SysDictDataMapper dictDataMapper;

    /**
     * 浏览日志记录
     *
     * @param logEvent 浏览日志事件
     */
    @Async
    @EventListener
    public void recordVisit(VisitLogEvent logEvent) {
        SysVisitLogBo log = MapstructUtils.convert(logEvent, SysVisitLogBo.class);
        String pageUrl = log.getPageUrl();
        String title = "驼人官网";
        try {
            URI uri = new URI(pageUrl);
            String path = uri.getPath();
            String lastSegment = path.substring(path.lastIndexOf('/') + 1);
            // 获取配置中的综合区域
            List<SysDictDataVo> dictList = dictDataMapper.selectDictDataByType("sys_visit_title").stream().filter(o->lastSegment.equals(o.getDictValue())).collect(Collectors.toList());
            title = dictList!=null && dictList.size()>0 ?dictList.get(0).getDictLabel() : title;

        } catch (URISyntaxException e) {
            e.printStackTrace();
        }finally {
            log.setTitle(title);
            // 远程查询操作地点
            log.setOperLocation(AddressUtils.getRealAddressByIP(log.getOperIp()));
            insertVisitLog(log);
        }
    }

    @Override
    public TableDataInfo<SysVisitLogVo> selectPageVisitLogList(SysVisitLogBo log, PageQuery pageQuery) {
        LambdaQueryWrapper<SysVisitLog> lqw = buildQueryWrapper(log);
        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("oper_id");
            pageQuery.setIsAsc("desc");
        }
        Page<SysVisitLogVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(page);
    }

    private LambdaQueryWrapper<SysVisitLog> buildQueryWrapper(SysVisitLogBo visitLog) {
        Map<String, Object> params = visitLog.getParams();
        return new LambdaQueryWrapper<SysVisitLog>()
            .like(StringUtils.isNotBlank(visitLog.getOperIp()), SysVisitLog::getOperIp, visitLog.getOperIp())
            .like(StringUtils.isNotBlank(visitLog.getTitle()), SysVisitLog::getTitle, visitLog.getTitle())
            .eq(visitLog.getBusinessType() != null && visitLog.getBusinessType() > 0,
                SysVisitLog::getBusinessType, visitLog.getBusinessType())
            .func(f -> {
                if (ArrayUtil.isNotEmpty(visitLog.getBusinessType())) {
                    f.in(SysVisitLog::getBusinessType, Arrays.asList(visitLog.getBusinessType()));
                }
            })
            .eq(visitLog.getStatus() != null,
                SysVisitLog::getStatus, visitLog.getStatus())
            .between(params.get("beginTime") != null && params.get("endTime") != null,
                SysVisitLog::getOperTime, params.get("beginTime"), params.get("endTime"));
    }

    /**
     * 新增浏览日志
     *
     * @param bo 浏览日志对象
     */
    @Override
    public void insertVisitLog(SysVisitLogBo bo) {
        SysVisitLog log = MapstructUtils.convert(bo, SysVisitLog.class);
        log.setOperTime(new Date());
        baseMapper.insert(log);
    }

    /**
     * 查询系统浏览日志集合
     *
     * @param bo 浏览日志对象
     * @return 浏览日志集合
     */
    @Override
    public List<SysVisitLogVo> selectVisitLogList(SysVisitLogBo bo) {
        LambdaQueryWrapper<SysVisitLog> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw.orderByDesc(SysVisitLog::getOperId));
    }

    /**
     * 批量删除系统浏览日志
     *
     * @param operIds 需要删除的浏览日志ID
     * @return 结果
     */
    @Override
    public int deleteVisitLogByIds(Long[] operIds) {
        return baseMapper.deleteByIds(Arrays.asList(operIds));
    }

    /**
     * 查询浏览日志详细
     *
     * @param operId 浏览ID
     * @return 浏览日志对象
     */
    @Override
    public SysVisitLogVo selectVisitLogById(Long operId) {
        return baseMapper.selectVoById(operId);
    }

    /**
     * 清空浏览日志
     */
    @Override
    public void cleanVisitLog() {
        baseMapper.delete(new LambdaQueryWrapper<>());
    }
}
